package com.chinamsp.dydb.convert;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ClassUtils;

import com.chinamsp.dydb.dbsource.DataSourceSettings;
import com.chinamsp.dydb.util.BizUtils;

/**
 * orm name 转换执行器
 * @author shifenghu
 *
 */
public class ORMNameConverter implements InitializingBean, ORMNameStrategy, ApplicationContextAware{

	/**
	 * ORMNameConverter 实例 
	 */
	public static ORMNameConverter INSTANCE;
	
	
	public ORMNameConverter() {
		INSTANCE = this;
	}
	
	/**
	 * dao 和 class 对应的关系
	 */
	private final Map<Class<?>, Class<?>> modelClassCached = new HashMap<Class<?>, Class<?>>(128);
	
	/**
	 * dao 和 class 对应的关系
	 */
	private final Map<Class<?>, Class<?>> daoClassCached = new HashMap<Class<?>, Class<?>>(128);
	
	/**
	 * model class 和 biz 的关系
	 */
	private final Map<Class<?>, Class<?>> bizClassCached = new HashMap<Class<?>, Class<?>>(128);
	
	/**
	 * 实际的 orm 处理方式
	 */
	private ORMNameStrategy ormNameStrategy;
	
	private ApplicationContext applicationContext;
	
	@Autowired
	private DataSourceSettings dataSourceSettings;
	
	@Override
	public String convertToDao(String modelClassName) {
		return ormNameStrategy.convertToDao(modelClassName);
	}


	@Override
	public String convertToBiz(String modelClassName) {
		return ormNameStrategy.convertToBiz(modelClassName);
	}


	@Override
	public String convertToModel(String daoClassName) {
		return ormNameStrategy.convertToModel(daoClassName);
	}


	@Override
	public String convertToField(String property) {
		return ormNameStrategy.convertToField(property);
	}


	@Override
	public String convertToSchema(String className) {
		return ormNameStrategy.convertToSchema(className);
	}
	
	@Override
	public String parseModuleName(String tableName) {
		return ormNameStrategy.parseModuleName(tableName);
	}
	
	/**
	 * 根据 model class 获取 dao class
	 * @param modelClass
	 * @return 
	 */
	public Class<?> getDaoClass(Class<?> modelClass){
		Class<?> clazz = daoClassCached.get(modelClass);
		//如果 clazz 不存在缓存中
		if(clazz == null){
		    clazz = BizUtils.forName(convertToDao(modelClass.getName()));
			daoClassCached.put(modelClass, clazz);
			modelClassCached.put(clazz, modelClass);
		}
		return clazz;
	}
	

	
	/**
	 * 根据 dao class 获取 对应的model class
	 * @param daoClass
	 * @return
	 */
	public Class<?> getModelClass(Class<?> daoClass){
		Class<?> clazz = modelClassCached.get(daoClass);
		if(clazz == null){
			try {
				clazz = ClassUtils.forName(convertToModel(daoClass.getName()), ClassUtils.getDefaultClassLoader());
			}catch (Throwable e) {
				throw new IllegalArgumentException(e);
			}
			//放入缓存
			modelClassCached.put(daoClass, clazz);
			daoClassCached.put(clazz, daoClass);
		}
		return clazz;
	}
	
	
	/**
	 * 根据 model class 获取 biz class
	 * @param modelClass
	 * @return 
	 */
	public Class<?> getBizClass(Class<?> modelClass){
		Class<?> clazz = bizClassCached.get(modelClass);
		//如果 clazz 不存在缓存中
		if(clazz == null){
			//将 string 转换成 clazz
			try {
				clazz = ClassUtils.forName(convertToBiz(modelClass.getName()), ClassUtils.getDefaultClassLoader());
			} catch (Exception e) {
				throw new IllegalArgumentException(e);
			}
			bizClassCached.put(modelClass, clazz);
		}
		return clazz;
	}
	
	
	

	@Override
	public void afterPropertiesSet() throws Exception {
		ormNameStrategy = (ORMNameStrategy) applicationContext.getBean(dataSourceSettings.getOrmNameConvertStrategy());
	}
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}
